#include "applet.h"
#include "ui_applet.h"
#include <QByteArray>
#include <QCryptographicHash>
#include <QPluginLoader>
#include <QProcess>
#include <QPainterPath>
#include <QScreen>

static int g_receivedTimes = 0;
static int g_oneFileTotalDataSize = 0;
static int g_currentReceiveDataSize = 0;    //The size of the received data in the current file
static int g_hasReceivedDataSize = 0;   //Accumulated uploaded file size (for multiple files)
static int g_allFilesDataSize = 0;  //Size of all uploaded files
static QString g_filename;
static QString g_fileType;
static QStringList g_allFileNamesAndSize;
static QString g_fileAndSize;
static QString SHA256;
static QFile *g_file;
static QByteArray g_buffer;
static QString g_savePath;
static int g_screenWidth;
static int g_screenHeight;

applet::applet(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::applet)
{
    ui->setupUi(this);
    QScreen *screen = qApp->primaryScreen();
    g_screenWidth = screen->size().width();
    g_screenHeight = screen->size().height();
}

applet::~applet()
{
    delete ui;
}

void applet::setQrCode(QPixmap pixmap,int port)
{
    g_currentPixmap = pixmap;
    g_myPort = port;
    double scale;
    QScreen *screen = qApp->primaryScreen();
    qreal realX = screen->physicalDotsPerInchX();
    qreal realWidth = g_screenWidth / realX * 2.54;

    if(realWidth < 15)
    {
        scale=0;
    }
    else if (realWidth < 18)
    {
        scale=0.5;
    }
    else
    {
        scale=0.8;
    }

    QPixmap scaled = pixmap.scaled(pixmap.size() * scale,
                                   Qt::KeepAspectRatio,
                                   Qt::FastTransformation);

    ui->label_Image->setPixmap(scaled);
}

void applet::startServerForReceiveFile()
{
    g_tcpServer = new QTcpServer(this);

    qDebug() << "g_myPort = " << g_myPort;
    g_tcpServer->listen(QHostAddress::Any,g_myPort);
    g_timer = new QTimer(this);
    g_timer->setInterval(1);
    g_messagebox->setText(tr("The mini program is processing file data. Please wait a moment..."));

    connect(g_tcpServer,&QTcpServer::newConnection,[=](){
        g_tcpSocket = g_tcpServer->nextPendingConnection();
        g_messagebox->show();
        connect(g_timer, &QTimer::timeout, [=](){
            QString str = "1";
            g_tcpSocket->write(str.toUtf8());
            qDebug() <<"g_tcpSocket->write(1)";
            g_timer->stop();
        });
        connect(g_tcpSocket,&QTcpSocket::readyRead,[=](){
            /*The first connection obtains the file name, and subsequent file data will be obtained*/
            QByteArray data = g_tcpSocket->readAll();
            if(g_receivedTimes == 0){
                g_messagebox->close();
                QString first_data = QString::fromUtf8(data);
                qDebug() <<"first_data = " << first_data;
                g_allFileNamesAndSize = first_data.section(":",0,0).split("*");
                g_allFilesDataSize = first_data.section(":",1,1).toInt();
                //                if(g_allFilesDataSize >= 10000000){
                //                    g_messagebox->setText(tr("Please select files smaller than 10M to upload！"));
                //                    g_messagebox->exec();
                //                    g_tcpSocket->close();
                //                    g_tcpServer->close();
                //                    g_timer->stop();
                //                    on_pushButton_clicked();
                //                    return;
                //                }
                //                else
                //                {
                qDebug() << "g_allFilesDataSize = " << g_allFilesDataSize;
                //                }

                for(QString  s : g_allFileNamesAndSize){
                    QString tmp = s.split(".").last();
                    g_fileType = tmp.section("/",0,0);
                    //                    if(g_fileType != "plt" && g_fileType != "dxf" && g_fileType != "png" && g_fileType != "bmp" && g_fileType != "pbm" && g_fileType != "jpg"){

                    //                        g_messagebox->setText(tr("The type of the incoming file cannot have") + g_fileType);
                    //                        g_messagebox->exec();
                    //                        closeAll(g_tcpSocket,g_file);
                    //                        return;
                    //                    }
                }

                g_allFilesDataSize = first_data.section(":",1,1).toInt();

                bool res = openFileAndJudgeType(g_tcpSocket);
                if(!res){
                    return;
                }
            }
            else
            {
                g_hasReceivedDataSize += data.size();
                ui->label_4->setText(QString("%1%").arg(g_hasReceivedDataSize * 100 / g_allFilesDataSize));
                qDebug() <<"g_oneFileTotalDataSize = " << g_oneFileTotalDataSize << "g_currentReceiveDataSize = " << g_currentReceiveDataSize;

                //Currently received file data of size one or more
                if(g_currentReceiveDataSize + data.size() >= g_oneFileTotalDataSize){

                    int last_remaining_size = g_oneFileTotalDataSize - g_currentReceiveDataSize;

                    g_file->write(data.left(last_remaining_size));
                    g_buffer += data.left(last_remaining_size);
                    /*Delete the data from the previous file to ensure that the starting data is from the next file*/
                    data.remove(0,last_remaining_size);
                    if(!verify(g_tcpSocket))
                        return; //If any problems are found during file verification, the transfer will be terminated directly
                    while(data.size() > 0){
                        qDebug() <<"data.size = " << data.size();
                        bool res = openFileAndJudgeType(g_tcpSocket);
                        if(!res)
                            return;
                        /*If during the process of splitting the remaining data, it is found that its size is greater than or equal to the size of the file being processed,
                                the file will be written while continuing to move forward*/
                        if(g_oneFileTotalDataSize <= data.size()){
                            g_file->write(data.left(g_oneFileTotalDataSize));
                            g_buffer += data.left(g_oneFileTotalDataSize);
                            data.remove(0,g_oneFileTotalDataSize);
                            qDebug() <<"g_file.size = " << g_file->size();
                            if(!verify(g_tcpSocket))
                                return;
                        }
                        else
                        {
                            g_file->write(data);
                            g_buffer += data;
                            g_currentReceiveDataSize = data.size();
                            break;
                        }
                    }
                    //File transfer completed
                    if(g_allFilesDataSize == g_hasReceivedDataSize ){
                        if(g_file->isOpen()){
                            if(!verify(g_tcpSocket)) return;
                        }
                        //QMessageBox::information(this,tr("prompt"),tr("All files have been successfully uploaded"));
                        //                             g_messagebox->setText(tr("All files have been successfully uploaded"));
                        //                             g_messagebox->show();
                        emit send_file_update_msg();
                        closeAll(g_tcpSocket,g_file);
                        return;
                    }
                }
                else
                {   //A file has not been fully collected
                    g_file->write(data);
                    g_buffer += data;
                    g_currentReceiveDataSize += data.size();
                }
            }
            g_timer->start();
            ++g_receivedTimes;
        });
    });
}

bool applet::verify(QTcpSocket * tcp)
{
    QCryptographicHash sha256(QCryptographicHash::Sha256);
    sha256.addData(g_buffer);
    QByteArray hashRes = sha256.result();
    QString hashedData = QString::fromUtf8(hashRes.toHex());
    qDebug() << "hashedData = " << hashedData;

    g_file->close();
    if(hashedData != SHA256){
        QString info = tr("Verified by SHA256, file ") + g_filename.split("/").last() +tr("Data error occurred during transmission, please try again");
        g_messagebox->setText(info);
        g_messagebox->exec();
        closeAll(g_tcpSocket,g_file);
        return false;
    }
    g_buffer.clear();
    return true;
}

bool applet::openFileAndJudgeType(QTcpSocket * tcp)
{
    //Data preprocessing
    g_fileAndSize = g_allFileNamesAndSize.first();
    qDebug() <<" g_fileAndSize = " << g_fileAndSize;

    g_allFileNamesAndSize.removeFirst();
    g_filename = g_savePath;
    g_filename += g_fileAndSize.section("/",0,0);

    qDebug() <<"g_filename = " << g_filename;

    QString section2 = g_fileAndSize.section("/",1,1);
    g_oneFileTotalDataSize = section2.section("|",0,0).toInt();
    SHA256 = section2.section("|",1,1);
    qDebug() <<"SHA256 = " << SHA256;

    g_file = new QFile(g_filename);
    if(!g_file->open(QFile::WriteOnly)){
        g_messagebox->setText(tr("Failed to open file, end file upload"));
        g_messagebox->exec();
        g_tcpSocket->close();
        g_tcpServer->close();
        on_pushButton_clicked();
        return false;
    }
    //Decompose the file name suffix
    QStringList templist;
    //QString templast = templist.last();
    templist = g_filename.split(".");
    g_fileType = templist.last();

    return true;
}

void applet::closeAll(QTcpSocket * tcp,QFile * g_file)
{
    g_tcpSocket->close();
    g_tcpServer->close();

    if(g_file){
        g_file->close();

    }
    g_timer->stop();
    g_timer->deleteLater();
    on_pushButton_clicked();

}

void applet::on_pushButton_clicked()
{
    ///ui->progressBar->setValue(0);
    ui->label_4->setText("0%");
    g_oneFileTotalDataSize = 0;
    g_currentReceiveDataSize = 0;
    g_allFilesDataSize = 0;
    g_hasReceivedDataSize = 0;
    g_receivedTimes = 0;

    //g_messagebox->close();

    if(g_buffer.size() > 0) g_buffer.clear();

    if(g_tcpServer->isListening()){
        g_tcpServer->close();

    }
    close();
}

void applet::setSavePath(QString path)
{
    g_savePath = path;
}

void applet::languageReload()
{
    ui->retranslateUi(this);
}
